package com.atguigu.tingshu.order.service.impl;

import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.dto.PaymentDto;
import com.atguigu.tingshu.model.order.OrderDetail;
import com.atguigu.tingshu.model.order.OrderInfo;
import com.atguigu.tingshu.order.mapper.OrderDetailMapper;
import com.atguigu.tingshu.order.mapper.OrderInfoMapper;
import com.atguigu.tingshu.order.service.OrderPayService;
import com.atguigu.tingshu.payment.client.PaymentFeignClient;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.annotation.Resource;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.concurrent.TimeUnit;

/**
 * @Author GQS @Date 2024/11/13/19:42 @Description
 * 订单支付的相关接口
 */
@Service
public class OrderPayServiceImpl implements OrderPayService {

  @Autowired
  private OrderInfoMapper orderInfoMapper;

  @Resource
  private PaymentFeignClient paymentFeignClient;

  @Autowired
  private RedisTemplate redisTemplate;

  @Autowired
  private RedissonClient redissonClient;

  @Autowired
  private RabbitTemplate rabbitTemplate;

  @Autowired
  private OrderDetailMapper orderDetailMapper;
  /**
   * 获取订单的支付地址
   * @param orderNo
   * @return
   */
  @Override
  public Object getOrderPayAddress(String orderNo) {
    //获取用户id
    Long userId = AuthContextHolder.getUserId();
    //查询订单的数据
    OrderInfo orderInfo =
            orderInfoMapper.selectOne(
                    new LambdaQueryWrapper<OrderInfo>()
                            .eq(OrderInfo::getUserId, userId)//指定用户
                            .eq(OrderInfo::getOrderNo, orderNo)//指定订单号
                            .eq(OrderInfo::getOrderStatus, "0901")//必须是未支付
            );
    if (orderInfo == null){
      throw new GuiguException(201, "订单不存在,无法支付");
    }
    // 获取支付渠道
    String payWay = orderInfo.getPayWay();
    // 上锁 限制一个订单号十分钟只能申请一个支付地址
    Object o = redisTemplate.opsForHash().get("PayAddress" + orderNo, payWay);
    if (o != null){
      return o;
    }
    // 向微信申请地址的参数初始化
    PaymentDto paymentDto = new PaymentDto();
    paymentDto.setPayway(payWay);
    paymentDto.setOrderNo(orderNo);
    paymentDto.setBody(orderInfo.getOrderTitle());
    paymentDto.setMoney(orderInfo.getOrderAmount().multiply(new BigDecimal(100)).intValue() + ""); // 元转化为分
    paymentDto.setExchange("payment_tingshu_order_exchange");
    paymentDto.setRoutingKey("payment.order.tingshu");
    paymentDto.setUserId(AuthContextHolder.getUserId());

    //申请支付地址: 远程调用支付微服务
    String payAddress = paymentFeignClient.getPayAddress(paymentDto);
    //记录这个地址: 有效期是10分钟
    redisTemplate.opsForHash().put("PayAddress_" + orderNo, payWay, payAddress);
    redisTemplate.expire("PayAddress_" + orderNo, 10, TimeUnit.MINUTES);
    //返回
    return payAddress;
  }

  /**
   * 查询订单的支付结果
   * 给工作人员查询结果用的
   * @param orderNo
   * @return
   */
  @Override
  public Object getOrderPayResult(String orderNo) {
    //获取用户id
    Long userId = AuthContextHolder.getUserId();
    //每刷新3-5次,查询一次
    Long increment =
            redisTemplate.opsForValue().increment(
                    "Order_Pay_Result_Query_Count_" + orderNo + "_" + userId,
                    1);
    // 客户端每发送5次请求 查询一次订单数据
    if(increment.intValue()%5 == 0){
      OrderInfo orderInfo =
              orderInfoMapper.selectOne(
                      new LambdaQueryWrapper<OrderInfo>()
                              .eq(OrderInfo::getUserId, userId)//指定用户
                              .eq(OrderInfo::getOrderNo, orderNo)//指定订单号
              );
      // 订单为空 抛异常
      if(orderInfo == null){
        throw new GuiguException(201, "订单不存在!");
      }
      // 如果订单状态不是已支付
      // if(!orderInfo.getOrderStatus().equals("0902")){
      //查询订单的支付状态
      // if(paymentFeignClient.getPayResult(orderNo, orderInfo.getPayWay())){
      //   //TODO-修改订单的状态为: 已支付!!!!!
      //
      //   //清理计数器
      //   redisTemplate.expire("Order_Pay_Result_Query_Count_" + orderNo + "_" + userId, 1, TimeUnit.MINUTES);
      // }

      // }
      // Boolean payResult = paymentFeignClient.getPayResult(orderNo, orderInfo.getPayWay()); // boolean无法序列化
      return "支付成功";
    }


    return null;
  }

  /**
   * 修改订单的支付状态orderStatus
   * @param orderNo
   */
  @Override
  public void updateOrderPaid(String orderNo) {
    // 根据orderNo查询orderInfo
    OrderInfo orderInfo =
            orderInfoMapper.selectOne(
                    new LambdaQueryWrapper<OrderInfo>()
                            .eq(OrderInfo::getOrderNo, orderNo));
    // 查询itemId
    OrderDetail orderDetail = orderDetailMapper.selectOne(new LambdaQueryWrapper<OrderDetail>()
                                                                  .eq(OrderDetail::getOrderId, orderInfo.getId()));
    Long itemId = orderDetail.getItemId();
    // 如果订单状态为已支付 直接返回
    if(orderInfo.getOrderStatus().equals("0902")){
      return;
    }
    //获取用户id
    Long userId = orderInfo.getUserId();
    //获取锁!!!
    RLock lock = redissonClient.getLock("Order_Cancel_" + orderInfo.getId() + "_User_" + userId);
    //加锁
    lock.lock();
    try {
      //修改为已支付
      orderInfo.setOrderStatus("0902");
      if(orderInfoMapper.updateById(orderInfo) < 0){
        throw new GuiguException(201, "修改订单已支付失败!");
      }
    }catch (Exception e){
      throw e;
    }finally {
      lock.unlock();
    }
    // 删除下单时加的死锁
    redisTemplate.delete(userId + "-" + itemId); // 没必要: 会自动过期 且商品已经购买过了
    //消息队列进行通知: 广播 通知每个服务根据订单号操作数据
    rabbitTemplate.convertAndSend("order_paid_fanout_exchange", "", orderNo);
    //专辑: 专辑服务:购买次数+1 搜索服务:热度+ 购买量+1  用户服务: 用户专辑购买记录新增 账户服务: 记录消费

    //会员: 用户服务:修改vip +时间 账户服务: 记录消费

    //声音: 专辑服务:购买次数+N 搜索服务:热度+ 购买量+N 用户服务: 用户声音购买记录新增 账户服务: 记录消费
  }
}
